#ifndef __MYSQLQUERY_H__
#define __MYSQLQUERY_H__

#include <map>
#include <string>
#include <string.h>
#include <stdexcept>
#include <cppconn/driver.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/metadata.h>
#include <cppconn/resultset_metadata.h>
#include <cppconn/exception.h>
#include <cppconn/warning.h>
#include "boost/shared_ptr.hpp"
#include "../../util/cpp/util/gwsingletonhelper.h"
#include "../../util/cpp/util/gwreference.hpp"

/**
*@file       dbqueryservice.h
*@brief      mysql query
*
*@author     graywind
*@version    1.0.0.0
*@data       2012/01/17
*/

class MysqlService
{
	GW_DeclareInterfaceSingleton(MysqlService);

public:
	///define pointee of prepared statement 
	typedef boost::shared_ptr<sql::PreparedStatement>       PreStmtPtr;
	///define pointee of statement
	typedef boost::shared_ptr<sql::Statement>               StmtPtr;

private:
	///database connection
    class MysqlConnection
    {
    private:
	    ///whether opened
	    bool             m_bIsOpen;
	    ///database connection
	    sql::Connection* m_dbConn;
	    ///database url
	    std::string      m_strUrl;
	    ///database user name
	    std::string      m_userName;
	    ///database password
	    std::string      m_passWord;
	    ///database schema
	    std::string      m_schemaName;

    public:
	    ///@brief constructor
	    ///param[in]   databaseIP    ip address of the mysql server 
	    ///param[in]   databasePort  server port of the mysql server 
	    ///param[in]   schema        name of the schema
	    ///param[in]   usr           user name  of the mysql server 
	    ///param[in]   psw           passworld  of the mysql server 
	    MysqlConnection(const std::string& databaseIP, int databasePort, const std::string& schema, const std::string& usr, const std::string& psw);
	    ///@brief destructor
	    ~MysqlConnection();

    public:
	    ///@brief   open this connection
	    ///retval   void
	    void Open();
	    ///@brief   whether open this connection
	    ///retval   bool
	    bool IsOpen() const;
	    ///@brief   close this connection
	    ///retval   void
	    void Close();

	public:
		///@brief   create a statement
		///param[in]   sql_sentence     SQL
		///retval   StmtPtr(smart pointer of statement)
		MysqlService::StmtPtr           CreateStatement();
		///@brief   create a prepared statement
		///param[in]   sql_sentence     SQL
		///retval   PreStmtPtr(smart pointer of statement)
		MysqlService::PreStmtPtr        CreatePreparedStatement(const std::string& sql_sentence);
    };

private:
        ///define connection ptr type
        typedef boost::shared_ptr<MysqlConnection>   MysqlConnPtr;
	///define prpared statement container
	typedef std::map<std::string, PreStmtPtr>    PreStmtPtrMap;

private:
	///define connection unit
	struct stConnectionUnit
	{
	        ///contains the connection ptr
	        MysqlConnPtr   ConnPtr;
	        ///prepared statement map
	        PreStmtPtrMap  PreMap;
	        ///@brief constructor
	        stConnectionUnit(MysqlConnPtr  ptr);
	};

private:
        ///define connection container
        typedef std::map<int, stConnectionUnit*>   ConnectionMap;

private:
	///connection map
	ConnectionMap        m_connMap;

public:
	///@brief  open a connection
	///param[in]   id           the connection identifier which user specified
	///param[in]   databaseIP   ip address of mysql server
	///param[in]   databasePort port of mysql server
	///param[in]   schema       which schema be connected
	///param[in]   usr          user name of mysql server
	///param[in]   psw          password of mysql server
	///retval  void
	void OpenConnection(int id, const std::string& databaseIP, int databasePort, const std::string& schema, const std::string& usr, const std::string& psw);
	///@brief  check a connection is alive
	///param[in]   id      the connection identifier
	///retval  bool
	bool IsConnectionOpen(int id) const;
	///@brief  close a connection
	///param[in]   id      the connection identifier
	///retval  void
	void CloseConnection(int id);
	///@brief  close all connection
	///retval  void
	void CloseAll();

public:
	///@brief   get a statement created by the connection
	///param[in]  connectionId    the connection identifier
	///param[in]  sql_sentence    SQL
	///retval   StmtPtr(smart pointer of statement)
	StmtPtr            GetStatement(int connectionId);
	///@brief   get a prepared statement created by the connection
	///param[in]  connectionId    the connection identifier
	///param[in]  sql_sentence    prepared SQL
	///retval   PreparedStmtPtr(smart pointer of prepared statement)
	PreStmtPtr         GetPreparedStatement(int connectionId, const std::string& sql_sentence);

};

/***************************************************************************************************************************/
///initialize prepared statement when the connection is opened
class PreStmtInitializer
{
        GW_DeclareInterfaceSingleton(PreStmtInitializer);


        friend class MysqlService;
public:
        ///define target map
        typedef std::map<std::string, gwBedrockUtil::gwReference<MysqlService::PreStmtPtr> > TargetMap;
        ///define initialize map
        typedef std::map<int, TargetMap> InitMap;

private:
        ///init map
        InitMap   m_mapInit;

public:
        ///@brief  add the initial map
        ///param[in]  conn_id   connection identifier
        ///param[in]  &p        reference to the pointer
        ///param[in]  sql       sql sentence
        ///retval  void
        void Add(int conn_id, MysqlService::PreStmtPtr& p, const std::string& sql);
};


#endif
